/*
 * Wazuh Vulnerability scanner - Scan Orchestrator
 * Copyright (C) 2015, Wazuh Inc.
 * March 11, 2024.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#ifndef _BUILD_ALL_AGENT_INFO_CONTEXT_HPP
#define _BUILD_ALL_AGENT_INFO_CONTEXT_HPP

#include "chainOfResponsability.hpp"
#include "loggerHelper.h"
#include "scanContext.hpp"
#include "socketDBWrapper.hpp"
#include "vulnerabilityScanner.hpp"
#include "wazuhDBQueryBuilder.hpp"
#include "wdbDataException.hpp"

/**
 * @brief Orchestrates queries over the global Wazuh system
 *
 * This class is responsible for managing the execution of queries within the global Wazuh environment.
 *
 * @tparam TScanContext scan context type.
 */
template<typename TScanContext = ScanContext, typename TSocketDBWrapper = SocketDBWrapper>
class TBuildAllAgentListContext final : public AbstractHandler<std::shared_ptr<TScanContext>>
{

public:
    /**
     * @brief Construct a new global fetch object
     */
    explicit TBuildAllAgentListContext() = default;

    /**
     * @brief Handles request and passes control to the next step of the chain.
     *
     * The `handleRequest` method processes incoming requests, executes queries in the Wazuh-DB, and forwards the
     * query response to a sub-orchestration component. The handling involves several steps:
     *
     * 1. It instantiates the socketWrapper for the Wazuh-DB if it hasn't been created.
     * 2. Executes a query in the Wazuh-DB to fetch data.
     * 3. Sends the query response to sub-orchestration as a scan context.
     *
     * @param data A shared pointer to the input data containing details of the query request.
     *
     * @note This function may interact with the Wazuh-DB, perform query operations, and create a scan context
     *       to pass to the sub-orchestration. It may also throw exceptions in the event of errors.
     *
     * @return A shared pointer to a `TScanContext` object representing the query response.
     */
    std::shared_ptr<TScanContext> handleRequest(std::shared_ptr<TScanContext> data) override
    {
        nlohmann::json response;

        try
        {
            // Execute query
            TSocketDBWrapper::instance().query(
                WazuhDBQueryBuilder::builder().globalGetCommand("all-agents context").build(), response);
        }
        catch (const SocketDbWrapperException& e)
        {
            throw WdbDataException(e.what(), "all");
        }
        catch (std::exception& e)
        {
            logError(WM_VULNSCAN_LOGTAG, "Unable to retrieve global agents data. Reason: %s.", e.what());
            return nullptr;
        }

        const auto isManagerScanDisabled = PolicyManager::instance().getManagerDisabledScan();
        for (const auto& agent : response)
        {
            try
            {
                // If the agent is the manager and the manager scan is disabled, skip it
                if (!(isManagerScanDisabled && agent.at("id").get<int>() == 0))
                {
                    data->m_agents.push_back(
                        {Utils::padString(std::to_string(agent.at("id").get<int>()), '0', 3),
                         agent.at("name"),
                         agent.contains("version") ? Utils::leftTrim(agent.at("version"), "Wazuh ") : "",
                         agent.at("ip")});
                }
                else
                {
                    logDebug2(WM_VULNSCAN_LOGTAG, "Skipping manager agent with id 0."); // LCOV_EXCL_LINE
                }
            }
            // LCOV_EXCL_START
            catch (const std::exception& e)
            {
                logDebug2(WM_VULNSCAN_LOGTAG, "Error reading global agent data: %s", e.what());
            }
            // LCOV_EXCL_STOP
        }
        logDebug2(WM_VULNSCAN_LOGTAG, "Fetched %d agents from Wazuh-DB.", data->m_agents.size());
        return AbstractHandler<std::shared_ptr<TScanContext>>::handleRequest(std::move(data));
    }
};

using BuildAllAgentListContext = TBuildAllAgentListContext<>;

#endif // _BUILD_ALL_AGENT_INFO_CONTEXT_HPP
